#include "insn.h"
#include "uarch/sim.h"

Insn::Insn (opcode_t opcode, paddr_t addr, uint8_t dest, uint8_t src1, uint8_t src2, uint64_t imm)
{
    this->opcode = opcode;
    this->addr = addr;
    this->dest = dest;
    this->src1 = src1;
    this->src2 = src2;
    this->imm = imm;
}

Insn::~Insn (void)
{
}

bool Insn::is_memop (void)
{
    return ((opcode & OpMask) == OpMem);
}

Mreq *Insn::create_mreq (void)
{
    Mreq *request;

    if (!is_memop ())
        fatal_error ("Insn::create_mreq should never be called on non-memory insn.");

    switch (opcode & OpSubMask)
    {
    case OpMemLd: request = new Mreq (C_GETIS, addr); break;
    case OpMemSt: request = new Mreq (C_GETIM, addr); break;
    case OpSynLd: request = new Mreq (LL, addr); break;
    case OpSynSt: request = new Mreq (SC, addr); break;
    case OpSync:  request = new Mreq (SYNC, addr); break;
    default:
        fatal_error ("Insn::create_mreq - unknown mem operation\n");
    }
    return request;
}

void Insn::dump (void)
{
    switch (opcode)
    {
    case OpNop: fprintf (stderr, "Nop"); break;
    case OpInt:
        switch (opcode & OpSubMask)
        {
        case OpIntALU: fprintf (stderr, "IntALU"); break;
        case OpIntMul: fprintf (stderr, "IntMul"); break;
        case OpIntDiv: fprintf (stderr, "IntDiv"); break;
        }
        break;
    case OpFp:
        switch (opcode & OpSubMask)
        {
        case OpFpALU: fprintf (stderr, "FpALU"); break;
        case OpFpMul: fprintf (stderr, "FpMul"); break;
        case OpFpDiv: fprintf (stderr, "FpDiv"); break;
        }
        break;
    case OpBr:
        switch (opcode & OpSubMask)
        {
        case OpBrJump: fprintf (stderr, "Jump"); break;
        case OpBrCond: fprintf (stderr, "BrCond"); break;
        case OpBrCall: fprintf (stderr, "Call"); break;
        case OpBrCCall: fprintf (stderr, "CCall"); break;
        case OpBrRet: fprintf (stderr, "Ret"); break;
        case OpBrCRet: fprintf (stderr, "CRet"); break;
        case OpBrTrap: fprintf (stderr, "Trap"); break;
        case OpBrCTrap: fprintf (stderr, "CTrap"); break;
        }
        break;
    case OpMem:
        switch (opcode & OpSubMask)
        {
        case OpMemLd: fprintf (stderr, "Load"); break;
        case OpMemSt: fprintf (stderr, "Store"); break;
        case OpSynLd: fprintf (stderr, "Load Link"); break;
        case OpSynSt: fprintf (stderr, "Store Cond"); break;
        case OpSync: fprintf (stderr, "Sync"); break;
        }
        break;
    default:
        fatal_error ("Insn::dump - unknown opcode\n");
    }
}
